package com.haoxuer.discover.filter.base;

import com.haoxuer.discover.filter.common.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class RetryFilterProxy implements Filter {

  private static Logger log = LoggerFactory.getLogger(RetryFilterProxy.class);

  protected int numOfRetries = 3;
  protected int waitTimeInMs = 50;
  protected int waitIncreaseFactor = 5;

  private final Handler delegateServlet;

  public RetryFilterProxy(Handler servlet) {
    this.delegateServlet = servlet;
  }


  @Override
  public void doFilter(HandlerRequest request, HandlerResponse response, FilterChain filterChain) {

    long waitTime = waitTimeInMs;
    int failedAttempts = 0;

    do {
      if (failedAttempts > 0) {
        log.info("Waiting for {}ms before retrying the command.", waitTime);
        waitBeforeRetry(waitTime);
        waitTime *= waitIncreaseFactor;
      }

      try {
        delegateServlet.service(request,response);
        break;
      } catch (Exception e) {
        log.info("Caught optimistic locking exception: " + e);
      }
      failedAttempts++;
    } while (failedAttempts <= numOfRetries);

  }

  protected void waitBeforeRetry(long waitTime) {
    try {
      Thread.sleep(waitTime);
    } catch (InterruptedException e) {
      log.debug("I am interrupted while waiting for a retry.");
    }
  }

  public void setNumOfRetries(int numOfRetries) {
    this.numOfRetries = numOfRetries;
  }

  public void setWaitIncreaseFactor(int waitIncreaseFactor) {
    this.waitIncreaseFactor = waitIncreaseFactor;
  }

  public void setWaitTimeInMs(int waitTimeInMs) {
    this.waitTimeInMs = waitTimeInMs;
  }

  public int getNumOfRetries() {
    return numOfRetries;
  }

  public int getWaitIncreaseFactor() {
    return waitIncreaseFactor;
  }

  public int getWaitTimeInMs() {
    return waitTimeInMs;
  }
}
